﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Windows.Threading;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;

namespace APC_Application.Pages
{
    /// <summary>
    /// Interaction logic for ExercisePage.xaml
    /// </summary>
    public partial class ExercisePage : UserControl, ISwitchable
    {
        private const int CanvasWidth = 1366;
        private const int CanvasHeight = 768;

        private const int NumberOfRectanglesHorzintal = 10;
        private const int NumberOfRectanglesVertical = 5;

        private const int MaxPulseLimit = 100;
        private const int MinPulseLimit = 50;

        private int timeToExercice = 60*15;

        private int _numberOfRetangles;
        private int _progression;
        private int _secounds;
        private readonly DispatcherTimer _timer;
        private readonly DispatcherTimer _timeLeft;

        private BluetoothClient _client;
        private readonly Collection<int> _pulseList = new Collection<int>(); 
        private readonly Collection<int> _saturationList = new Collection<int>();

        private List<Rectangle> _rectangleList = new List<Rectangle>();
        private readonly List<string> _motivationalMessagesList = new List<string>
        {
            "You are doing fine!",
            "You are working it.",
            "That's it! Keep up the good work." ,
            "You are almost there",
            "Wup wup",
            "Great!",
            "You are killing it!",
            "Sprint to the finish line.",
            "What?!?! Tour de france, here we come!"
        };

        private readonly int _messageInterval;

        public ExercisePage()
        {
            // Set image
            //var imageArray = new List<Uri>();
            //imageArray.Add(new Uri("../Images/family_photo.jpg"));
            //imageArray.Add(new Uri("../Images/family_photo2.jpg"));
            //imageArray.Add(new Uri("../Images/family_photo3.jpg"));
            //imageArray.Add(new Uri("../Images/family_photo4.jpg"));
            //var randomGenerator = new Random();
            //int random = randomGenerator.Next();
            //int index = random % imageArray.Count;
            //FamilyPhotoImage.Source = new BitmapImage(imageArray[index]);
            

            InitializeComponent();
            PulseSlider.Ticks.Add(MinPulseLimit);
            PulseSlider.Ticks.Add(MaxPulseLimit);
            DataContext = this;

            _numberOfRetangles = NumberOfRectanglesHorzintal * NumberOfRectanglesVertical;
            _messageInterval = (int)Math.Floor(_numberOfRetangles / (double)_motivationalMessagesList.Count);

            SimulationSlider.Maximum = _numberOfRetangles;

            GenerateRectangles();

            _timer = new DispatcherTimer();
            _timer.Tick += timer_tick;
            _timer.Interval = new TimeSpan(0, 0, 0, 1);
            _timer.Start();


            _timeLeft = new DispatcherTimer();
            _timeLeft.Tick += timeLeft_tick;
            _timeLeft.Interval = new TimeSpan(0, 0, 0, 1);
            _timeLeft.Start();

            content.Visibility = Visibility.Hidden;
            //if (BluetoothRadio.IsSupported)
                StartBloodPressureDevice(new BluetoothClient());
        }

        private void GenerateRectangles()
        {
            var rectangleWidth = Math.Ceiling(CanvasWidth / (double)NumberOfRectanglesHorzintal);
            var rectangleHeight = Math.Ceiling(CanvasHeight / (double)NumberOfRectanglesVertical);

            var tmpRectangleList = new List<Rectangle>();

            var colorBrushList = new List<SolidColorBrush>
            {
                Brushes.CadetBlue,
                Brushes.Brown,
                Brushes.Chocolate,
                Brushes.BlueViolet,
                Brushes.CornflowerBlue,
                Brushes.DarkBlue,
                Brushes.DarkGreen,
                Brushes.Crimson,
                Brushes.Chartreuse,
                Brushes.DarkSeaGreen,
                Brushes.DeepPink,
                Brushes.Coral,
                Brushes.DimGray,
                Brushes.Black,
            };

            var randomNumber = new Random();

            for (var i = 0; i < NumberOfRectanglesHorzintal; i++)
            {
                for (var j = 0; j < NumberOfRectanglesVertical; j++)
                {
                    var posX = i * rectangleWidth;
                    var posY = j * rectangleHeight;

                    var rect = new Rectangle
                    {
                        Fill = colorBrushList.ElementAt(randomNumber.Next(colorBrushList.Count)),
                        Width = rectangleWidth,
                        Height = rectangleHeight
                    };

                    tmpRectangleList.Add(rect);

                    Canvas.SetLeft(rect, posX);
                    Canvas.SetTop(rect, posY);

                    PhotoCanvas.Children.Add(rect);
                }
            }

            _rectangleList = tmpRectangleList.OrderBy(item => randomNumber.Next()).ToList();
        }

        private void StartBloodPressureDevice(BluetoothClient bluetoothClient)
        {
            _client = bluetoothClient;
            var thread = new Thread(GetData);
            var nonindevice = _client.DiscoverDevices().FirstOrDefault(x => x.DeviceName == "Nonin_Medical_Inc._680956");
       
            
            if (nonindevice != null)
            {
                content.Visibility = Visibility.Visible;
                ConnectingLabel.Visibility = Visibility.Hidden;
                Console.WriteLine("Conntected to " + nonindevice.DeviceName);
            }

            bool run = false;

            while (!run)
            {
                try
                {
                    if (nonindevice != null)
                    {
                        _client.Connect(nonindevice.DeviceAddress, BluetoothService.SerialPort);
                        if (_client.Connected)
                        {
                            run = true;
                            var start_byte = new Byte[6];
                            start_byte[0] = 2;
                            start_byte[1] = 112;
                            start_byte[2] = 2;
                            start_byte[3] = 2;
                            start_byte[4] = 08;
                            start_byte[5] = 3;
                            _client.Client.Send(start_byte);

                            thread.Start();
                        }
                    }
                }
                catch (Exception e)
                {
                    // Handle exception
                }
            }
            
        }

       
        private void timer_tick(object sender, EventArgs e)
        {
            _secounds++;
            if (_pulseList.Any())
            {
                if (_pulseList.Last() > MinPulseLimit && _pulseList.Last() < MaxPulseLimit)
                {
                    if (HideNextRectangle())
                    {
                        _timer.Stop();
                        FinishMessage.Visibility = Visibility.Visible;
                    }
                }
            }
        }

        private void timeLeft_tick(object sender, EventArgs e)
        {
            int minLeft = timeToExercice/60;
            int secondsLeft = timeToExercice%60;
            if (secondsLeft < 10)
            {
                TimeLabel.Content = minLeft + ":0" + secondsLeft;
            }
            else
            {
                TimeLabel.Content = minLeft + ":" + secondsLeft;
            }

          
            timeToExercice--;
        }

        private bool HideNextRectangle()
        {
            if (_rectangleList.Count == 0)
            {
                MotivationalMessageBorder.Visibility = Visibility.Hidden;
                ListsModel model = new ListsModel();
                model.pulse = _pulseList;
                model.saturation = _saturationList;
                Switcher.Switch(new FinishPage(),model);
                return true;
            }

            var rect = _rectangleList.First();
            rect.Visibility = Visibility.Hidden;
            _rectangleList.Remove(rect);

            _progression++;
            if (_messageInterval == _progression && _motivationalMessagesList.Count > 0)
            {
                MotivationalMessageBorder.Visibility = Visibility.Visible;
                var msg = _motivationalMessagesList.First();
                MotivationalMessageTextBlock.Text = msg;
                _motivationalMessagesList.Remove(msg);
                _progression = 0;
            }

            return false;
        }

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if (HideNextRectangle())
            {
                _timer.Stop();
                FinishMessage.Visibility = Visibility.Visible;
            }
        }

        public void UtilizeState(object state)
        {
            throw new NotImplementedException();
        }

        private void FinishExerciseButton_Click(object sender, RoutedEventArgs e)
        {
            var averagePuls = _pulseList.Any() ? _pulseList.Average() : 0;
            Switcher.Switch(new FinishPage(), averagePuls);
        }

        public void GetData()
        {
            while (true)
            {
                var buffer = new byte[1024];
                _client.Client.Receive(buffer);

                var pulse = buffer[1];
                var saturation = buffer[2];

                _pulseList.Add(pulse);
                _saturationList.Add(saturation);

                if (pulse > MinPulseLimit && pulse < MaxPulseLimit)
                {
                    PulseLabel.Dispatcher.Invoke(new Action(() => PulseLabel.Foreground = new SolidColorBrush(Colors.Green)));
                    PulseSlider.Dispatcher.Invoke(new Action(() => PulseSlider.Background = new SolidColorBrush(Colors.Green)));
                }
                else
                {
                    PulseLabel.Dispatcher.Invoke(new Action(() => PulseLabel.Foreground = new SolidColorBrush(Colors.Red)));
                    PulseSlider.Dispatcher.Invoke(new Action(() => PulseSlider.Background = new SolidColorBrush(Colors.Red)));
                }
                PulseSlider.Dispatcher.Invoke(new Action(() => PulseSlider.Value = pulse));
                PulseLabel.Dispatcher.Invoke(new Action(() => PulseLabel.Content = pulse.ToString()));
                SaturationLabel.Dispatcher.Invoke(new Action(() => SaturationLabel.Content = saturation.ToString()));

                Thread.Sleep(500);
            }
        }
    }
}
